import usePrevious from '@/hooks/usePrevious';
import React, { useEffect, useRef, useState } from 'react';

import './index.less';

interface IProps {
  active: boolean;
  children: JSX.Element;
}

interface IActiveContainersProps {
  active: React.Key;
  config: { component: JSX.Element; key: React.Key }[];
  enableSilentLoad?: boolean;
}

const ActiveContainer = (props: IProps) => {
  const { active, children } = props;

  const renderFlag = useRef<Boolean>(false);

  // 从未渲染过且出发首次激活时，更新标记
  useEffect(() => {
    if (renderFlag.current) {
      return;
    }
    if (active) {
      renderFlag.current = true;
      // console.log('初次激活渲染')
    }
  }, [active]);

  // 从未激活时，不渲染
  if (!active && !renderFlag.current) {
    return <></>;
  }
  // 激活至少一次后，控制显示隐藏，不重新渲染
  return <div style={{ display: active ? '' : 'none' }}>{children}</div>;
};

/**
 * 性能优化后的容器管理，控制同一区域的不同容器展示，会静默加载不可见的容器，从而在进入时完成数据准备与内容渲染，但会首次渲染请求较多
 * @param props
 * @returns
 */
export const ActiveContainers = (props: IActiveContainersProps) => {
  const { active, config, enableSilentLoad = true } = props;

  const loaded = useRef<React.Key[]>([]);
  const [loadFlag, setLoadFlag] = useState(0);
  const [showTarget, setShowTarget] = useState<React.Key>(active); // 需要脱离hide状态的容器
  const [showAniTarget, setShowAniTarget] = useState<React.Key>(active); // 需要脱离hide状态的容器
  const lastActive = usePrevious<React.Key>(active);

  useEffect(() => {
    if (!enableSilentLoad) {
      return;
    }
    silentLoad();
  }, [loadFlag]);

  useEffect(() => {
    if (lastActive !== active) {
      setShowAniTarget(active)
      setTimeout(() => {
        setShowTarget(active);
      }, 200);
    }
  }, [active]);

  const silentLoad = () => {
    if (loaded.current.length === config.length) {
      return;
    }
    console.log('完成加载', loaded.current);
    for (const i of config) {
      // 后台加载没有被加载过的容器进行准备
      if (!loaded.current.includes(i.key)) {
        loaded.current.push(i.key);
        break;
      }
    }
    setLoadFlag(loadFlag + 1);
  };

  const renderContent = () => {
    if (!loaded.current.includes(active)) {
      loaded.current.push(active);
    }
    return config
      .filter((i) => loaded.current.includes(i.key))
      .map((i) => (
        <div
          style={{ display: (i.key !== showTarget && i.key !== showAniTarget) ? 'none' : '' }}
          className={[
            'active-item',
            i.key === active ? 'active-item--active' : 'active-item--inactive',
          ].join(' ')}
          key={i.key}
        >
          {i.component}
        </div>
      ));
  };

  return <>{renderContent()}</>;
};

export default ActiveContainer;
